
#ifndef __moab_libmesh_wrapper_h__
#define __moab_libmesh_wrapper_h__

// C++ includes
#include <vector>

//#include "moab/Core.hpp"
#include "MBTagConventions.hpp"

//using namespace libMesh;
//using namespace moab;

// Forward declarations
namespace libMesh {
class Elem;
class MeshBase;
class EquationSystems;
}

namespace moab {
class ParallelComm;
class Core;
}

class MOAB_libMesh_Wrapper
{
public:

  /**
   * Constructor.  Takes a read-only reference to a mesh object
   * and a MOAB Interface object
   * This is the constructor required to write a mesh.
   */
  MOAB_libMesh_Wrapper (Core* iface, unsigned int n_systems = 2 );

  ~MOAB_libMesh_Wrapper ();

  /**
   * This method implements writing a mesh with nodal data to a
   * specified file where the nodal data and variable names are provided.
   */
  ErrorCode write_equation_systems (const std::string& fname,
						const EquationSystems& physics, unsigned int isystem,
						bool build_solutions = true, bool build_adjacencies = false,
						bool verbose = false
						);

  ErrorCode write_equation_systems_parallel (const std::string& fname,
						const EquationSystems& physics, unsigned int isystem,
						bool build_solutions = true, bool build_adjacencies = false,
						bool verbose = false);

  std::vector<EntityHandle>& get_root_sets () ;

  std::vector<moab::ParallelComm *>& get_parallel_communicators() ;

  std::vector<EntityHandle>& get_partition_handles() ;

  // static constant ID's for various types of Entity Sets
  static const int EMPTY_SET_ID  = 1100;
  static const int VERTEX_SET_ID = 1101;
	static const int EDGE_SET_ID   = 1102;
	static const int FACE_SET_ID   = 1103;
  static const int REGION_SET_ID = 1104;
  static const int SET_SET_ID    = 1105;

  static EntityType cell_type(const Elem* elem);

  static void cell_connectivity(const Elem* elem, std::vector<unsigned int>& vtk_cell_connectivity);

private:

  ErrorCode write_equation_systems_parallel_old (const std::string& fname,
						const EquationSystems& physics, unsigned int isystem);

  EntityHandle make_set( unsigned int options,
                         EntityHandle* entities,
                         size_t num_entities,
                         bool reverse,
                         const int id = 0 ) ;

  EntityHandle make_set( unsigned int options,
                         Range& entities,
                         bool reverse,
                         const int id = 0 ) ;

  Core* mdbImpl;
  iMesh_Instance imesh;
  unsigned int n_systems;

  // other private, system dependent objects
  std::vector<EntityHandle> root_sets ;
  std::vector<moab::ParallelComm *> parallel_communicators ;
  std::vector<EntityHandle> partition_handles ;

};

// Inline functions

inline
std::vector<EntityHandle>& MOAB_libMesh_Wrapper::get_root_sets ()
{
  return root_sets;
}

inline
std::vector<moab::ParallelComm *>& MOAB_libMesh_Wrapper::get_parallel_communicators()
{
  return parallel_communicators;
}

inline
std::vector<EntityHandle>& MOAB_libMesh_Wrapper::get_partition_handles()
{
  return partition_handles;
}


#endif // #define __moab_libmesh_wrapper_h__
